
////////////////////////////////////////////////////////////////////////////
//	File Name: glibplus.h		Last modification at : 10/25/2002 11:23:06 AM
//	Copyright 1999-2002 Microsoft Corporation. All Rights Reserved.
//
//	Author:      Rong Xiao
//	Email :      i-rxiao@microsoft.com
//
//	Description : 
//
//	Revision History: 
//
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GLIBPLUS_H__
#define __GLIBPLUS_H__

#pragma warning( disable : 4786 )

#include "glib.h"
#include "../CommonUsed/TMatrix.h"
#include <atlbase.h>
#include <gdiplus.h>

#pragma comment( lib, "gdiplus.lib" )


enum IMG_TYPE { BMP_TYPE=0x00, JPG_TYPE=0x01};

class GDIManager {
protected:
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
public:
	// Initialize Gdiplus.
	GDIManager() {Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);	}
	//Shutdown Gdiplus
	~GDIManager() {Gdiplus::GdiplusShutdown(gdiplusToken);}
};



class CGdiImage  {
protected:
	Gdiplus::Bitmap * m_pImage;
	int m_ByteCount;
	int m_iLocked;

public:
	void Free();
	
	CGdiImage() : m_pImage(0), m_iLocked(0) {}
	CGdiImage(Gdiplus::Bitmap* pImg) : m_pImage(pImg), m_iLocked(1) {}
	~CGdiImage() {Free();}
	Gdiplus::Bitmap * LockBmp() { 
		m_iLocked++;
		return m_pImage;
	}
	int GetWidth() const { 
		assert(m_pImage);
		return m_pImage->GetWidth();
	}
	int GetHeight() const { 
		assert(m_pImage);
		return m_pImage->GetHeight();
	}

	void UnLockBmp() { if (m_iLocked>0) m_iLocked--; } 
	bool ConvertTo24BitBmp();
	bool ConvertTo8BitBmp();

	
	bool Img2Mat(TByteMat& mat);
	bool Img2RGBMat(TUIntMat& mat);
	bool Mat2Img(const TByteMat& mat);
	bool RGBMat2Img(const TUIntMat& mat);
	bool Load(const char* pszFileName);
	bool Save(const char* pszName, int imageFormat=BMP_TYPE);
	void Rotate(float flRotate);
	void Crop(RECT& rect);
	//bExpand==true, center is disabled.
	void Rotate(CGdiImage& img,  Gdiplus::PointF& center, float flRotate, BOOL bExpand);
};

int GetPixelByte(Gdiplus::PixelFormat pixelFormat );
bool Img2RGBMat(Gdiplus::Bitmap *pImage, TUIntMat& mat);
bool Img2Mat(Gdiplus::Bitmap *pImage, TByteMat& mat);
Gdiplus::Bitmap *GetImgFromBuf(BYTE* pBufSrc, int nRows, int nCols, Gdiplus::PixelFormat pixelFormat, BYTE*& pBufDst, BYTE*& pBmpHeader);
bool Mat2Bmp(const TUIntMat& mat,const char* pszName, int imageFormat=BMP_TYPE);
bool Mat2Bmp(const TByteMat& mat,const char* pszName, int imageFormat=BMP_TYPE);
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid); 
bool Save(Gdiplus::Bitmap *pImage, const char* pszName, int imageFormat=BMP_TYPE);


template <typename U, typename V>
bool MatZoom(FAST::TMatrix<U>& matIn, FAST::TMatrix<V>& matOut, int nDstW, int nDstH)
{
	int nSrcH=matIn.GetRows();
	int nSrcW=matIn.GetCols();

	CGdiImage imgSrc;
	TByteMat matGrayIn, matGrayOut;
	TUIntMat matColorIn, matColorOut;

	if ( sizeof (U) == 1 ) {
		matGrayIn=matIn;
		imgSrc.Mat2Img(matGrayIn);
	}
	else if ( sizeof (U) == 4 )
	{
		matColorIn=matIn;
		imgSrc.RGBMat2Img(matColorIn);
	}
	else 
		return false;
	
	if ( sizeof (V) == 1 ) 
		matGrayOut.NewSize(nDstH, nDstW);
	else if ( sizeof (V) == 4 ) 
		matColorOut.NewSize(nDstH, nDstW);

	else 
		return false;

	Gdiplus::Bitmap bmpDst(nDstW,nDstH, PixelFormat24bppRGB );
	Gdiplus::Graphics graphics(&bmpDst);
	Gdiplus::Rect dstRect(0,0,nDstW, nDstH), srcRect(0,0,nSrcW, nSrcH);
		
	graphics.DrawImage(imgSrc.LockBmp(),
		dstRect, 
		0, 0, nSrcW, nSrcH,
		Gdiplus::UnitPixel,	NULL,	NULL,			NULL);
	imgSrc.UnLockBmp();

	if ( sizeof (V) == 1 ) {
		Img2Mat(&bmpDst,matGrayOut);
		matOut=matGrayOut;
	}
	else if ( sizeof (V) == 4 ) {
		Img2RGBMat(&bmpDst,matColorOut);
		matOut = matColorOut;
	}
	else
		return false;

	return true;
}

#endif
